package noUsed;

/*
 * Lesson05.java
 *
 * Created on July 15, 2003, 11:30 AM
 */

import general.Mechanisme;
import graphique.C;

import java.awt.*;
import java.awt.event.*;

import javax.media.opengl.*;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.GLUquadric;

import com.sun.opengl.util.Animator;

/** Port of the NeHe OpenGL Tutorial (Lesson 5)
 * to Java using the Jogl interface to OpenGL.  Jogl can be obtained
 * at http://jogl.dev.java.net/
 *
 * @author Kevin Duling (jattier@hotmail.com)
 */


class Renderer implements GLEventListener, KeyListener, MouseMotionListener
{
	static Animator animator = null;

	static Mechanisme m;
	private float rquad = 0.0f;
	private float rtri = 0.0f;

	int QUADS = 1;
	int TRIANGLES = 2;
	int TERRAIN = 3;
	int SIPHERE = 4;

	private double angleX = 0;
	private double angleY = 45;

	int posMX;
	int posMY;

	/** Called by the drawable to initiate OpenGL rendering by the client.
	 * After all GLEventListeners have been notified of a display event, the 
	 * drawable will swap its buffers if necessary.
	 * @param gLDrawable The GLDrawable object.
	 */    
	public void display(GLAutoDrawable gLDrawable)
	{
		final GL gl = gLDrawable.getGL();
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

		/*
      gl.glLoadIdentity();
      gl.glTranslatef(-1.5f, 0.0f, -6.0f);
      gl.glRotatef(rtri, 0.0f, 1.0f, 0.0f);

      gl.glCallList(TRIANGLES);

      gl.glLoadIdentity();
      gl.glTranslatef(1.5f, 0.0f, -6.0f);
      gl.glRotatef(rquad, 1.0f, 1.0f, 1.0f);

      gl.glCallList(QUADS);
		 */
		GLU glu=new GLU();
		GLUquadric quadric=glu.gluNewQuadric();
		glu.gluQuadricNormals(quadric, GL.GL_TRUE);
		glu.gluQuadricDrawStyle(quadric, GLU.GLU_LINE );
		gl.glLoadIdentity();
		gl.glTranslatef( 0f, 0.0f, -6.0f);

		gl.glRotatef(rtri/20 , 1.0f, 1.0f, 0.0f);
		gl.glRotated( angleY , 1 , 0 , 0 );
		gl.glRotated( angleX , 0 , 0 , 1 );

		gl.glColor3f(0.0f,1,0.0f);
		glu.gluSphere(quadric, 2f, 32, 16);
		
		gl.glRotated( 90 , 0 , 1 , 0 );
		gl.glColor3f(1.0f,0,0.0f);
		//glu.gluSphere(quadric, 2f, 32, 16);
		gl.glRotated( -90 , 0 , 1 , 0 );
		
		/*
		gl.glRotated( 90 , 0 , 0 , 1 );
		gl.glColor3f(0.0f,0,1.0f);
		glu.gluSphere(quadric, 2f, 32, 16);
		*/
		//gl.glColor3f( 0 ,1.0f,0.0f);
		gl.glCallList(SIPHERE);
		//gl.glCallList(TERRAIN);
		/*
		gl.glRotatef(90 , 1.0f, 0, 0);

		gl.glCallList(TERRAIN);
		
		gl.glRotatef(-90 , 1.0f, 0, 0 );
		gl.glRotatef( 90 , 0.0f, 0 , 1);
		gl.glCallList(TERRAIN);*/
		//System.out.println(angleX);

		gl.glFlush();
		rtri += 1f;
		rquad += 0.15f;
	}

	double baseR = 1;

	double total;

	double modifRelief = 1;

	double modifTetha = 0.25;
	double modifPhi   = 0.25;

	double startTetha1 = Math.PI/2 + Math.PI/4;
	double startPhi1 = -Math.PI/4;//Math.PI;
	
	double startTetha2 = Math.PI/2+ Math.PI/4;
	double startPhi2 = -Math.PI/4;//Math.PI;

	
	double totalSI = 32;
	
	private void constructionDisplayList( GL gl )
	{		
		//totalSI = m.g.length;

		gl.glNewList( SIPHERE , GL.GL_COMPILE );

		for( int i = 0 ; i < totalSI-1 ; i += 1 )
		{
			gl.glBegin(gl.GL_LINES );

			for( int j = 0 ; j < totalSI-1  ; j += 1 )
			{
				gl.glColor3f( 0 , (float)j/(float)totalSI , (float)i/(float)totalSI );

				pointVertexSI( gl , i , j , totalSI );

				pointVertexSI( gl , i+1 , j , totalSI );

				pointVertexSI( gl , i+1 , j+1 , totalSI );

				pointVertexSI( gl , i , j+1 , totalSI );
			}
			gl.glEnd();
		}
		gl.glEndList();
		
		total = m.g.length;
		
		gl.glNewList( TERRAIN , GL.GL_COMPILE );

		for( int i = 0 ; i < total-1 ; i += 1 )
		{
			gl.glBegin(gl.GL_LINES );

			for( int j = 0 ; j < total-1  ; j += 1 )
			{
				gl.glColor3f( 0 , (float)j/(float)total , (float)i/(float)total );

				pointVertex( gl , i , j );

				pointVertex( gl , i+1 , j );

				pointVertex( gl , i+1 , j+1 );

				pointVertex( gl , i , j+1 );
				
			}
			gl.glEnd();
		}
		gl.glEndList();

		gl.glNewList( TRIANGLES , GL.GL_COMPILE );
		gl.glBegin(GL.GL_TRIANGLES);		    // Drawing Using Triangles
		gl.glColor3f(1.0f,0.0f,0.0f);			// Red
		gl.glVertex3f( 0.0f, 1.0f, 0.0f);			// Top Of Triangle (Front)
		gl.glColor3f(0.0f,1.0f,0.0f);			// Green
		gl.glVertex3f(-1.0f,-1.0f, 1.0f);			// Left Of Triangle (Front)
		gl.glColor3f(0.0f,0.0f,1.0f);			// Blue
		gl.glVertex3f( 1.0f,-1.0f, 1.0f);			// Right Of Triangle (Front)
		gl.glColor3f(1.0f,0.0f,0.0f);			// Red
		gl.glVertex3f( 0.0f, 1.0f, 0.0f);			// Top Of Triangle (Right)
		gl.glColor3f(0.0f,0.0f,1.0f);			// Blue
		gl.glVertex3f( 1.0f,-1.0f, 1.0f);			// Left Of Triangle (Right)
		gl.glColor3f(0.0f,1.0f,0.0f);			// Green
		gl.glVertex3f( 1.0f,-1.0f, -1.0f);			// Right Of Triangle (Right)
		gl.glColor3f(1.0f,0.0f,0.0f);			// Red
		gl.glVertex3f( 0.0f, 1.0f, 0.0f);			// Top Of Triangle (Back)
		gl.glColor3f(0.0f,1.0f,0.0f);			// Green
		gl.glVertex3f( 1.0f,-1.0f, -1.0f);			// Left Of Triangle (Back)
		gl.glColor3f(0.0f,0.0f,1.0f);			// Blue
		gl.glVertex3f(-1.0f,-1.0f, -1.0f);			// Right Of Triangle (Back)
		gl.glColor3f(1.0f,0.0f,0.0f);			// Red
		gl.glVertex3f( 0.0f, 1.0f, 0.0f);			// Top Of Triangle (Left)
		gl.glColor3f(0.0f,0.0f,1.0f);			// Blue
		gl.glVertex3f(-1.0f,-1.0f,-1.0f);			// Left Of Triangle (Left)
		gl.glColor3f(0.0f,1.0f,0.0f);			// Green
		gl.glVertex3f(-1.0f,-1.0f, 1.0f);			// Right Of Triangle (Left)
		gl.glEnd();				// Finished Drawing The Triangle
		gl.glEndList();

		gl.glNewList( QUADS , GL.GL_COMPILE );

		gl.glBegin(GL.GL_QUADS);           	// Draw A Quad
		gl.glColor3f(0.0f,1.0f,0.0f);			// Set The Color To Green
		gl.glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Top)
		gl.glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Top)
		gl.glVertex3f(-1.0f, 1.0f, 1.0f);			// Bottom Left Of The Quad (Top)
		gl.glVertex3f( 1.0f, 1.0f, 1.0f);			// Bottom Right Of The Quad (Top)

		gl.glColor3f(1.0f,0.5f,0.0f);			// Set The Color To Orange
		gl.glVertex3f( 1.0f,-1.0f, 1.0f);			// Top Right Of The Quad (Bottom)
		gl.glVertex3f(-1.0f,-1.0f, 1.0f);			// Top Left Of The Quad (Bottom)
		gl.glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Bottom)
		gl.glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Bottom)

		gl.glColor3f(1.0f,0.0f,0.0f);			// Set The Color To Red
		gl.glVertex3f( 1.0f, 1.0f, 1.0f);			// Top Right Of The Quad (Front)
		gl.glVertex3f(-1.0f, 1.0f, 1.0f);			// Top Left Of The Quad (Front)
		gl.glVertex3f(-1.0f,-1.0f, 1.0f);			// Bottom Left Of The Quad (Front)
		gl.glVertex3f( 1.0f,-1.0f, 1.0f);			// Bottom Right Of The Quad (Front)

		gl.glColor3f(1.0f,1.0f,0.0f);			// Set The Color To Yellow
		gl.glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Back)
		gl.glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Back)
		gl.glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Back)
		gl.glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Back)

		gl.glColor3f(0.0f,0.0f,1.0f);			// Set The Color To Blue
		gl.glVertex3f(-1.0f, 1.0f, 1.0f);			// Top Right Of The Quad (Left)
		gl.glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Left)
		gl.glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Left)
		gl.glVertex3f(-1.0f,-1.0f, 1.0f);			// Bottom Right Of The Quad (Left)

		gl.glColor3f(1.0f,0.0f,1.0f);			// Set The Color To Violet
		gl.glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Right)
		gl.glVertex3f( 1.0f, 1.0f, 1.0f);			// Top Left Of The Quad (Right)
		gl.glVertex3f( 1.0f,-1.0f, 1.0f);			// Bottom Left Of The Quad (Right)
		gl.glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Right)
		gl.glEnd();				// Done Drawing The Quad

		gl.glEndList();
	}
	
	private void pointVertexSI( GL gl, int i, int j , double totalP )
	{
		double x;
		double y;
		double z;

		double r;

		double theta1;
		double phi1;

		double theta2;
		double phi2;

		r = 2.1;//-(m.g[i][j] + baseR) * modifRelief;

		theta1 = (double)i/totalP  *2* Math.PI * modifTetha + startTetha1;
		phi1 = (double)j/totalP *2* Math.PI * modifPhi + startPhi1;
		
		theta2 = (double)i/totalP  *2* Math.PI * modifTetha + startTetha2;
		phi2 = (double)j/totalP *2* Math.PI * modifPhi + startPhi2;

		x = r * Math.cos( theta2 ) * Math.cos( phi2 );
		//y = r * Math.cos( theta2 ) * Math.cos( phi2 );
		y = r * Math.cos( theta2 ) * Math.sin( phi2 );
		z = r * Math.sin( theta2 );
		
		double yy = y * Math.cos( Math.PI/2 )-z * Math.sin( Math.PI/2 );
		double zz = y * Math.sin( Math.PI/2 )+z * Math.cos( Math.PI/2 );
		
		gl.glVertex3d( x , yy , zz );
	}

	private void pointVertex( GL gl, int i, int j )
	{
		double x;
		double y;
		double z;

		double r;

		double theta1;
		double phi1;

		double theta2;
		double phi2;

		r = 2.1;//-(m.g[i][j] + baseR) * modifRelief;

		theta1 = (double)i/total  *2* Math.PI * modifTetha + startTetha1;
		phi1 = (double)j/total *2* Math.PI * modifPhi + startPhi1;
		
		theta2 = (double)i/total  *2* Math.PI * modifTetha + startTetha2;
		phi2 = (double)j/total *2* Math.PI * modifPhi + startPhi2;

		x = r * Math.cos( theta1 ) * Math.cos( phi1 );
		//y = r * Math.cos( theta2 ) * Math.cos( phi2 );
		y = r * Math.cos( theta1 ) * Math.sin( phi1 );
		z = r * Math.sin( theta1 );

		gl.glVertex3d( x , y , z );
	}

	/** Called when the display mode has been changed.  <B>!! CURRENTLY UNIMPLEMENTED IN JOGL !!</B>
	 * @param gLDrawable The GLDrawable object.
	 * @param modeChanged Indicates if the video mode has changed.
	 * @param deviceChanged Indicates if the video device has changed.
	 */
	public void displayChanged(GLAutoDrawable gLDrawable, boolean modeChanged, boolean deviceChanged)
	{
	}

	/** Called by the drawable immediately after the OpenGL context is 
	 * initialized for the first time. Can be used to perform one-time OpenGL 
	 * initialization such as setup of lights and display lists.
	 * @param gLDrawable The GLDrawable object.
	 */
	public void init(GLAutoDrawable gLDrawable)
	{
		m = new Mechanisme();


		final GL gl = gLDrawable.getGL();
		gl.glShadeModel(GL.GL_SMOOTH);              // Enable Smooth Shading
		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    // Black Background
		gl.glClearDepth(1.0f);                      // Depth Buffer Setup
		gl.glEnable(GL.GL_DEPTH_TEST);							// Enables Depth Testing
		gl.glDepthFunc(GL.GL_LEQUAL);								// The Type Of Depth Testing To Do
		gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);	// Really Nice Perspective Calculations
		gLDrawable.addKeyListener(this);

		constructionDisplayList( gl );
	}


	/** Called by the drawable during the first repaint after the component has 
	 * been resized. The client can update the viewport and view volume of the 
	 * window appropriately, for example by a call to 
	 * GL.glViewport(int, int, int, int); note that for convenience the component
	 * has already called GL.glViewport(int, int, int, int)(x, y, width, height)
	 * when this method is called, so the client may not have to do anything in
	 * this method.
	 * @param gLDrawable The GLDrawable object.
	 * @param x The X Coordinate of the viewport rectangle.
	 * @param y The Y coordinate of the viewport rectanble.
	 * @param width The new width of the window.
	 * @param height The new height of the window.
	 */
	public void reshape(GLAutoDrawable gLDrawable, int x, int y, int width, int height)
	{
		final GL gl = gLDrawable.getGL();
		final GLU glu = new GLU();

		if (height <= 0) // avoid a divide by zero error!
			height = 1;
		final float h = (float)width / (float)height;
		gl.glViewport(0, 0, width, height);
		gl.glMatrixMode(GL.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(45.0f, h, 1.0, 20.0);
		gl.glMatrixMode(GL.GL_MODELVIEW);
		gl.glLoadIdentity();
	}

	/** Invoked when a key has been pressed.
	 * See the class description for {@link KeyEvent} for a definition of
	 * a key pressed event.
	 * @param e The KeyEvent.
	 */
	public void keyPressed(KeyEvent e)
	{
		if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
		{
			animator.stop();
			System.exit(0);
		}
	}

	/** Invoked when a key has been released.
	 * See the class description for {@link KeyEvent} for a definition of
	 * a key released event.
	 * @param e The KeyEvent.
	 */
	public void keyReleased(KeyEvent e) {}

	/** Invoked when a key has been typed.
	 * See the class description for {@link KeyEvent} for a definition of
	 * a key typed event.
	 * @param e The KeyEvent.
	 */
	public void keyTyped(KeyEvent e) {}



	public void mouseDragged(MouseEvent arg0)
	{
		double modifAngle = 130;

		int difX = posMX - arg0.getX();
		int difY = posMY - arg0.getY();

		double difAngleX = -(double)difX/C.taille * modifAngle;
		double difAngleY = (double)difY/C.taille * modifAngle;

		angleX += difAngleX;
		angleY += difAngleY;

		posMX = arg0.getX();
		posMY = arg0.getY();

		System.out.println(angleX);
	}

	public void mouseMoved(MouseEvent arg0)
	{
		posMX = arg0.getX();
		posMY = arg0.getY();


		//arg0.
	}

	/** Program's main entry point
	 * @param args command line arguments.
	 */
	public static void main(String[] args)
	{
		Frame frame = new Frame("Lesson 5: 3D Shapes");
		GLCanvas canvas = new GLCanvas(new GLCapabilities());
		canvas.addGLEventListener(new Renderer());
		canvas.addMouseMotionListener(new Renderer());
		frame.add(canvas);
		frame.setSize(640, 480);
		animator = new Animator(canvas);
		frame.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				animator.stop();
				System.exit(0);
			}
		});
		frame.show();
		animator.start();
		canvas.requestFocus();
	}

}
